package cn.kone.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.IdUtil;
import cn.kone.mapper.DriverMapper;
import cn.kone.pojo.domain.*;
import cn.kone.pojo.dto.LocationDTO;
import cn.kone.remote.api.UaaFeignApi;
import cn.kone.remote.dto.param.LoginDto;
import cn.kone.result.JSONResult;
import cn.kone.service.*;
import cn.kone.template.WechatTemplate;
import cn.kone.utils.AssertUtil;
import cn.kone.utils.NameUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.geo.Point;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.concurrent.TimeUnit;


/**
 * <p>
 * 司机对象 服务实现类
 * </p>
 *
 * @author yuyu
 * @since 2024-03-12
 */
@Service
@GlobalTransactional(name = "driverRegister&&Login")
public class DriverServiceImpl extends ServiceImpl<DriverMapper, Driver> implements IDriverService {


    //因为不是企业微信无法获取手机号信息,这里是直接写死;
    static final String phone = "13838384380";


    @Value("${head-portrait}")
    private String headPortrait;

//    @Autowired
//    private RestTemplate restTemplate;

    @Autowired
    private IDriverSettingService driverSettingService;

    @Autowired
    private IDriverSummaryService driverSummaryService;

    @Autowired
    private IDriverWalletService driverWalletService;

    @Autowired
    private UaaFeignApi uaaFeignApi;

    @Autowired
    private IDriverAuthMaterialService driverAuthMaterialService;

//    @Value("${appid}")
//    private String appId;
//
//    @Value("${appSecret}")
//    private String appSecret;

    //WechatTemplate这是自定义封装了一个获取openid的starter在这里可以直接注入使用
    @Autowired
    private WechatTemplate wechatTemplate;

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public Object getOpenId(String code) {

        /**
         * appid自己的微信小程序id
         * secret是小程序的秘钥
         * js_code是前端传递过来的Code
         */
        // 构建发送到微信API的HTTP GET请求，用于获取用户的OpenID等信息
//        String getOpenIdUrl = HttpUtil.get(
//                "https://api.weixin.qq.com/sns/jscode2session?appid="
//                        + appId + "&secret="
//                        + appSecret + "&js_code="
//                        + code + "&grant_type=authorization_code");
//        // 将微信API返回的JSON格式响应字符串解析为JSONObject对象，方便后续操作
//        JSONObject jsonObject = JSONObject.parseObject(getOpenIdUrl, JSONObject.class);
//        // 从JSONObject对象中提取出用户的OpenID字段的值
//        String openid = jsonObject.getString("openid");
//        // 打印获取到的用户OpenID到控制台，便于调试和查看
//        System.out.println("这是openid:" + openid);


        //通过自定义封装starter定义了一个wechatTemplate专门用来通过前端传递的code来获取openid
        String openId = wechatTemplate.getOpenId(code);
        System.out.println("这是通过wechatTemplate拿到的openid:" + openId);


        // 通过 openid 查询数据库中是否已存在对应的司机信息
        Driver one = getOne(new LambdaQueryWrapper<Driver>().eq(Driver::getOpenId, openId));
        // 如果查询结果不为空，表示已经存在相同 openid 的司机信息，如果查询结果不为空，则抛出异常并提供提示信息
        AssertUtil.isNull(one, "不要重复注册");

        //1.获取到openid以后需要初始化新注册司机用户对象保存到数据库中
        //1.1初始化司机对象
        Driver driver = new Driver();
        long driverId = IdUtil.createSnowflake(0, 0).nextId();
        driver.setId(driverId);
        driver.setPhone(phone);
        driver.setCreateTime(new Date());
        driver.setOpenId(openId);
        super.save(driver);

        //1.2初始化司机配置
        DriverSetting driverSetting = new DriverSetting();
        driverSetting.setId(driverId);
        driverSetting.setCreateTime(new Date());
        driverSettingService.save(driverSetting);


        //1.3.初始化司机结算表
        DriverSummary driverSummary = new DriverSummary();
        driverSummary.setId(driverId);
        driverSummary.setCreateTime(new Date());
        driverSummaryService.save(driverSummary);

        //1.4初始化司机钱包
        DriverWallet driverWallet = new DriverWallet();
        driverWallet.setId(driverId);
        driverWallet.setPassword("123456");
        driverWallet.setCreateTime(new Date());
        driverWalletService.save(driverWallet);


        //1.5初始化司机登陆信息
        LoginDto loginDto = new LoginDto();
        loginDto.setId(driverId);
        loginDto.setType(1);
        loginDto.setAvatar(headPortrait);
        loginDto.setNickName(NameUtil.getName());
        loginDto.setOpenId(driver.getOpenId());
        loginDto.setPhone(driver.getPhone());

        //测试分布式事务Seata有没有正常使用
//        System.out.println(1/0);

        JSONResult jsonResult = uaaFeignApi.saveLogin(loginDto);
        AssertUtil.isTrue(jsonResult.isSuccess(), "用户注册失败");

        return true;
    }


    /**
     * 提交实名认证材料
     *
     * @param driverAuthMaterial 实名认证材料对象
     * @return 返回实名认证状态，0表示审核中
     */
    @Override
    public Object submitRealNameMaterial(DriverAuthMaterial driverAuthMaterial) {
        // 设置司机ID为当前登录用户的ID
        driverAuthMaterial.setDriverId(StpUtil.getLoginIdAsLong());
        // 设置创建时间为当前时间
        driverAuthMaterial.setCreateTime(new Date());
        // 设置实名认证状态为审核中（0是审核）
        driverAuthMaterial.setRealAuthStatus(0); // 0是审核, 1是通过, 2是驳回

        driverAuthMaterial.setId(StpUtil.getLoginIdAsLong());
        // 保存实名认证材料
        driverAuthMaterialService.save(driverAuthMaterial);
        // 返回实名认证状态
        return driverAuthMaterial.getRealAuthStatus(); // 0是审核
    }

    /**
     * 获取已提交的实名认证材料
     *
     * @return 返回已提交的实名认证材料对象
     */
    @Override
    public Object getSubmitRealNameMaterial() {
        // 根据当前登录用户的ID查询实名认证材料并返回
        return driverAuthMaterialService.getById(StpUtil.getLoginIdAsLong());
    }

    //查询司机概要
    @Override
    public Object getSummary() {
        return driverSummaryService.getById(StpUtil.getLoginIdAsLong());
    }

    /**
     * 司机上线将接单配置缓存到Redis中
     *
     * @return
     */
    @Override
    public Object getOnline() {
        // 从数据库中获取当前登录用户的 driverSetting 数据
        // getById() 方法根据用户 ID 获取对应的 driverSetting 数据
        DriverSetting driverSetting = driverSettingService.getById(StpUtil.getLoginIdAsLong());
        AssertUtil.isNotNull(driverSetting, "没有配置~~");
        // 将获取到的 driverSetting 数据存储到 Redis 中
        // 使用了 RedisTemplate 对象 redisTemplate 来操作 Redis
        // boundValueOps() 方法返回一个用于操作 String 类型数据的操作对象
        // 这里将 driverSetting 数据以键值对的形式存储到 Redis 中
        // 键名为 "driverSetting" + 当前登录用户的 ID（使用 StpUtil.getLoginId() 获取登录用户的 ID）
        // 值为从数据库中获取到的 driverSetting 对象
        redisTemplate.boundValueOps("driverSetting" + StpUtil.getLoginIdAsLong()).set(driverSetting, 5, TimeUnit.MINUTES);


        return null;
    }

    //司机下线 删除Redis中的司机配置
    @Override
    public Object offLine() {

        redisTemplate.delete("driverSetting" + StpUtil.getLoginId());
        redisTemplate.delete("geo");
        return null;
    }


    //将程序启动后司机的实时定位缓存到Redis中
    @Override
    public Object saveGeo(LocationDTO locationDTO) {

        Point point = new Point(Double.valueOf(locationDTO.getLongitude()), Double.valueOf(locationDTO.getLatitude()));
        Long result = redisTemplate.boundGeoOps("geo").add(point, StpUtil.getLoginId());
        if (result == 1) {
            redisTemplate.expire("geo", 5, TimeUnit.MINUTES);
        }

        return null;
    }


}


